以往在同個網站切換網頁的時候,就會重新刷新頁面,然後等待資源重新載入才能看到新的畫面,但是人的耐心是有限的,每次的切換如果都需要等待的話,人的耐心就會被消磨殆盡, 使用者體驗就會不盡理想,因此SPA(single page application)單頁式應用的出現就是為了解決這個問題,切換頁面不會重新刷新,有效提升使用者體驗
React是靠react-router來實作,然後爬文一下發現,怎麼有react-router和react-router-dom?簡單介紹兩者的差異如下
所以實際上我們只要引入react-router-dom即可來實作react-router的功能
首先安裝react-router-dom
npm install react-router-dom
在index.js 引入
import { BrowserRouter, Switch } from 'react-router-dom';
BrowserRouter的用途:讓其底下所有的component都能使用router,可以利用HTML5 History來進行操作
Switch的用途:讓第一個吻合url的component被渲染,如果沒有switch,所有吻合的component都會被渲染
接著將用BrowserRouter、Switch 將app component包起來
ReactDOM.render(
<BrowserRouter>
<Switch>
<App />
</Switch>
</BrowserRouter>,
document.getElementById('root')
);
先引入Route,並且在app.js裡的jsx設定Route
import { Route } from 'react-router-dom';
Route的用途:幫路由設定對應的路徑和元件,可以說是用來定義哪個路徑配對哪個元件
<Route path="/" exact component={List} />
<Route path="/a" component={StateExample} />
<Route path="/b" component={Functional} />
Route 有幾個屬性如下:
exact:路徑需要完全符合才會導到該頁面等,等同於path===pathname,沒加的話點擊就造成 /、/a、/b均吻合路徑
path:路徑,用來比對URL
component:路徑吻合後,顯示對應的component
假如Route沒有寫path或是path='*', 並且排在前面的Route都沒被吻合的話就會被渲染,所以就可以拿來放一個預設頁面(404 not found)
<Route path="*">
<NoMatch404 />
</Route>
路徑的部分抽離出來放在nav.js控管
import React, { Component } from 'react';
import { Link, NavLink } from 'react-router-dom';
class Nav extends Component{
render(){
return(
<nav>
<Link to="/">index</Link>
<Link to="/a">a page</Link>
<Link to="/b">b page</Link>
</nav>
)
}
}
export default Nav
import {Link} from 'react-router-dom';
設定完Route之後,就要搭配Link來設定路徑,可以想像成是a連結的功能,只是點擊後不會重新跳轉
to 可以接受字串或是物件(location object)
字串
<link to="http://test.com" />
物件
<Link to{{
pathname: '/product',
search: '?sort=asc',
hash: '#hash',
state: { isMemeber: true }
}} />
NavLink
透過activeClassName="active" ,來設定與當前URL吻合時的項目要套用active樣式 ,可以想成是進階版的link
<NavLink activeClassName="active" to="/b">b page</NavLink>
BrowserRouter 網頁路徑 http://test.com/a, 需搭配server設定(ex apache、nginx),因為實際上並沒有a這個html檔案,所以不管使用者輸入什麼路徑都要導至index.html再交由react router控制
利用HTML5 history API提供的 pushState 、popState方法來控制路徑
HashRouter 網頁路徑會有#, ex.http://test.com/#b
利用window.location.hash 、hashchange控制路徑,透過改變#後面的值來切換頁面
但我是用BrowserRouter,居然也可以正常運作?那是因為create-react-app自動建立了express server的緣故,目前看到用React製作的網頁大部分都是使用BrowserRouter模式,畢竟網址當中多了個#看起來還是不太美觀
withRouter為一個HOC component,能將location、 history等資訊 作為props傳入component,一般而言只有包在Route裡面的component才能拿到路由的資訊,如果是麵包屑component(沒有被包在Route裡面)需要取得router的資訊就可以透過withRouter
import {withRouter} from 'react-router-dom'
function App(props){
console.log('props',props);
return (<div className='app'></div>)
}
export default withRouter(App); // 透過WithRouter將router等資訊傳入
印出props,可以看到有history、location,match等資訊
如同字面上的意思,用來重新導向,不會改變原有的網址
<Redirect to="/intro" />
參考資料
https://reactrouter.com/web/example/basic